<!--
 * @Description: 
 * @Author: 胡涛
 * @Date: 2023-12-01 21:34:16
 * @LastEditors: 胡涛
 * @LastEditTime: 2024-01-14 13:48:20
-->
<template>
  <a-modal
    :open="visible"
    :keyboard="false"
    :maskClosable="false"
    :title="title"
    @cancel="onCancel"
    @ok="onSubmit"
    :confirmLoading="submitLoading"
    :width="900"
  >
    <a-form ref="formRef" v-bind="formLayout" :model="model" :rules="rules">
      <a-tabs class="tabs">
        <a-tab-pane key="info" tab="基本信息">
          <a-form-item label="所属分类" prop="categoryId">
            <a-tree-select
              v-model:value="model.categoryId"
              :treeData="categoryItems"
              :fieldNames="{
                children: 'children',
                label: 'name',
                key: 'id',
                value: 'id',
              }"
            >
            </a-tree-select>
          </a-form-item>
          <a-form-item label="报表编码" prop="code">
            <a-input v-model:value="model.code"></a-input>
          </a-form-item>
          <a-form-item label="报表名称" prop="name">
            <a-input v-model:value="model.name"></a-input>
          </a-form-item>
          <a-form-item label="权限名称" prop="permissionName">
            <a-input v-model:value="model.permissionName"></a-input>
          </a-form-item>
          <a-form-item label="启用状态" prop="status">
            <a-checkbox v-model:checked="model.status">启用/停用</a-checkbox>
          </a-form-item>
          <a-form-item label="备注" prop="remarks">
            <a-input v-model:value="model.remarks" />
          </a-form-item>
        </a-tab-pane>
        <a-tab-pane key="request" tab="请求参数">
          <div class="grid">
            <div class="row row-header">
              <div class="cell cell-req-name">参数名</div>
              <div class="cell cell-req-desc">参数说明</div>
              <div class="cell cell-req-type">参数类别</div>
              <div class="cell cell-req-value">默认值</div>
              <div class="cell cell-req-input">输入组件</div>
              <div class="cell cell-req-action">操作</div>
            </div>
            <div
              class="row"
              v-for="(item, index) in model.requestOptions"
              :key="index"
            >
              <div class="cell cell-req-name">
                <a-input size="small" v-model:value="item.name" />
              </div>
              <div class="cell cell-req-desc">
                <a-input size="small" v-model:value="item.description" />
              </div>
              <div class="cell cell-req-type">
                <enum-select
                  size="small"
                  v-model:value="item.type"
                  name="RequestFieldTypeEnum"
                />
              </div>
              <div class="cell cell-req-value">
                <a-input size="small" v-model:value="item.defaultValue" />
              </div>
              <div class="cell cell-req-input" v-if="item.type == 1">
                <a-button
                  type="primary"
                  size="small"
                  @click="showConfigComponent(item)"
                  >配置</a-button
                >
                &nbsp;
                <span>{{ item.componentOptions?.name || "未配置" }}</span>
              </div>
              <div class="cell cell-req-input" v-else>-</div>
              <div class="cell cell-req-action">
                <a-button-group size="small">
                  <a-button
                    type="primary"
                    :disabled="index == 0"
                    @click="
                      model.requestOptions.splice(index, 1);
                      model.requestOptions.splice(index - 1, 0, item);
                    "
                    ><UpOutlined
                  /></a-button>
                  <a-button
                    type="primary"
                    :disabled="index == model.requestOptions.length - 1"
                    @click="
                      model.requestOptions.splice(index, 1);
                      model.requestOptions.splice(index + 1, 0, item);
                    "
                    ><DownOutlined
                  /></a-button>
                  <a-button
                    type="primary"
                    danger
                    @click="model.requestOptions.splice(index, 1)"
                    ><DeleteOutlined
                  /></a-button>
                </a-button-group>
              </div>
            </div>
          </div>
          <div class="bar">
            <a-button
              type="primary"
              @click="
                model.requestOptions.push({
                  name: '',
                  description: '',
                  defaultValue: '',
                  type: 1,
                  title: '',
                  formatter: {
                    type: 0,
                    name: '',
                    handler: '',
                  },
                  componentOptions: {
                    name: '',
                    props: {},
                    styles: {},
                    className: '',
                  },
                  displayRole: {
                    visible: true,
                    roles: [],
                  },
                })
              "
              >添加参数</a-button
            >
          </div>
        </a-tab-pane>
        <a-tab-pane key="source" tab="数据源" v-if="model.dataSource">
          <a-form-item label="接口地址" prop="dataSource.remoteUrl">
            <a-input-group compact>
              <a-input
                style="width: 85%"
                v-model:value="model.dataSource.remoteUrl"
              ></a-input>
              <a-button type="primary" style="width: 15%" @click="showApiConfig"
                >选择API接口</a-button
              >
            </a-input-group>
          </a-form-item>
          <a-form-item label="数据项键" prop="dataSource.itemsField">
            <a-input v-model:value="model.dataSource.itemsField"></a-input>
          </a-form-item>
          <a-row>
            <a-col :span="12">
              <a-form-item
                label="需要分页"
                prop="dataSource.isPaged"
                :="formLayout2"
              >
                <a-switch v-model:checked="model.dataSource.isPaged" />
              </a-form-item>
            </a-col>
            <a-col :span="12">
              <a-form-item
                label="包含汇总行"
                prop="dataSource.hasSummary"
                :="formLayout2"
              >
                <a-switch v-model:checked="model.dataSource.hasSummary" />
              </a-form-item>
            </a-col>
          </a-row>

          <a-form-item
            label="记录数键"
            prop="dataSource.totalField"
            v-if="model.dataSource.isPaged"
          >
            <a-input v-model:value="model.dataSource.totalField"></a-input>
          </a-form-item>
          <a-form-item
            label="汇总键"
            prop="dataSource.summaryField"
            v-if="model.dataSource.hasSummary"
          >
            <a-input v-model:value="model.dataSource.summaryField"></a-input>
          </a-form-item>
        </a-tab-pane>
        <a-tab-pane key="itemsHandler" tab="结果集处理" v-if="model.dataSource">
          <a-form-item label="需要手动处理">
            <a-switch
              v-model:checked="model.dataSource.requireHandler"
            ></a-switch>
          </a-form-item>
          <a-form-item label="处理脚本" v-if="model.dataSource.requireHandler">
            <monaco-editor
              :height="500"
              language="javascript"
              :options="{ fontSize: 17 }"
              v-model:value="model.dataSource.itemsHandler"
              :extraLibSource="itemsLibSource"
            ></monaco-editor>
          </a-form-item>
        </a-tab-pane>
        <a-tab-pane key="columns" tab="展示列">
          <div class="grid">
            <div class="row row-header">
              <div class="cell cell-name">字段名</div>
              <div class="cell cell-title">标题</div>
              <div class="cell cell-width">宽度</div>
              <div class="cell cell-align">对齐方式</div>
              <div class="cell cell-format">格式化</div>
              <div class="cell cell-action">操作</div>
            </div>
            <div
              class="row cell-name"
              v-for="(item, index) in model.reportColumns"
              :key="index"
            >
              <div class="cell cell-name">
                <a-input size="small" v-model:value="item.name" />
              </div>
              <div class="cell cell-title">
                <a-input size="small" v-model:value="item.title" />
              </div>
              <div class="cell cell-width">
                <a-input-number
                  :min="0"
                  :max="999"
                  size="small"
                  v-model:value="item.width"
                />
              </div>
              <div class="cell cell-align">
                <a-select
                  v-model:value="item.align"
                  size="small"
                  style="width: 100%"
                >
                  <a-select-option key="left" value="left"
                    >左对齐</a-select-option
                  >
                  <a-select-option key="center" value="center"
                    >居中对齐</a-select-option
                  >
                  <a-select-option key="right" value="right"
                    >右对齐</a-select-option
                  >
                </a-select>
              </div>
              <div class="cell cell-format">
                <a-button
                  type="primary"
                  size="small"
                  :value="item.formatter"
                  @click="formatterModel = { visible: true, config: item }"
                  >配置</a-button
                >
              </div>
              <div class="cell cell-action">
                <a-button-group size="small">
                  <a-button
                    type="primary"
                    :disabled="index == 0"
                    @click="
                      model.reportColumns.splice(index, 1);
                      model.reportColumns.splice(index - 1, 0, item);
                    "
                    ><UpOutlined
                  /></a-button>
                  <a-button
                    type="primary"
                    :disabled="index == model.reportColumns.length - 1"
                    @click="
                      model.reportColumns.splice(index, 1);
                      model.reportColumns.splice(index + 1, 0, item);
                    "
                    ><DownOutlined
                  /></a-button>
                  <a-button
                    type="primary"
                    danger
                    @click="model.reportColumns.splice(index, 1)"
                    ><DeleteOutlined
                  /></a-button>
                </a-button-group>
              </div>
            </div>
          </div>
          <div class="bar">
            <a-button
              type="primary"
              @click="
                model.reportColumns.push({
                  name: '',
                  title: '',
                  width: 0,
                  align: 'left',
                  formatType: 'default',
                  formatOptions: {},
                  formula: '',
                  formatter: '',
                  sortable: false,
                  styles: {},
                  props: {},
                  sortIndex: model.reportColumns.length + 1,
                })
              "
              >添加展示列</a-button
            >
          </div>
        </a-tab-pane>
        <a-tab-pane
          key="reportProps"
          tab="表格其它配置"
          v-if="model.reportProps"
        >
          <a-form-item label="配置">
            <a-checkbox v-model:checked="model.reportProps.useCustomHeader">
              自定义表头分组
            </a-checkbox>
            <a-checkbox v-model:checked="model.reportProps.useCustomCell">
              处理单元格合并
            </a-checkbox>
          </a-form-item>
          <a-form-item
            label="表头配置"
            v-if="model.reportProps.useCustomHeader"
          >
            <monaco-editor
              :height="260"
              language="json"
              :options="{ fontSize: 17 }"
              v-model:value="model.reportProps.headerConfig"
            ></monaco-editor>
          </a-form-item>
          <a-form-item
            label="单元格配置"
            v-if="model.reportProps.useCustomCell"
          >
            <monaco-editor
              :height="260"
              language="javascript"
              :options="{ fontSize: 17 }"
              v-model:value="model.reportProps.customCell"
              :extraLibSource="customCellLibSource"
              extraLibName="custom-cell"
            ></monaco-editor>
          </a-form-item>
        </a-tab-pane>
      </a-tabs>
    </a-form>
  </a-modal>
  <ConfigFormatterView
    v-if="formatterModel.visible"
    v-model:visible="formatterModel.visible"
    :config="formatterModel.config"
  />
  <SelectApiView
    v-if="selectApiModel.visible"
    v-model:visible="selectApiModel.visible"
    v-model:value="model.dataSource.apiConfigCode"
    v-model:url="model.dataSource.remoteUrl"
  />
  <ConfigComponentView
    v-if="componentModel.visible"
    v-model:visible="componentModel.visible"
    :config="componentModel.config"
  />
</template>

<script lang="ts" setup>
import { useFormPage } from "@/helpers/pages";
import { FormInstance, message } from "ant-design-vue";
import { computed, onMounted, ref, watch } from "vue";
import api from "@/api/report/reportConfig";
import {
  ReportConfigDto,
  ReportColumnConfig,
  ComponentOptions,
  ReportRequestFieldItem,
} from "@/api/report/types";
import ConfigFormatterView from "./components/ConfigFormatter.vue";
import SelectApiView from "./components/SelectApi.vue";
import ConfigComponentView from "./components/ConfigComponent.vue";
import {
  DeleteOutlined,
  UpOutlined,
  DownOutlined,
} from "@ant-design/icons-vue";
const formRef = ref<FormInstance>();
const emits = defineEmits(["update:visible", "close", "success"]);
const props = defineProps({
  id: String,
  visible: { type: Boolean, default: false },
  action: {
    type: String,
    default: "create",
  },
  item: {
    type: Object,
    default() {
      return {};
    },
  },
  categoryItems: { type: Array, required: true },
});
const formLayout2 = { labelCol: { span: 6 }, wrapperCol: { span: 16 } };
const { model, rules, formLayout, loading, submitLoading } = useFormPage<
  ReportConfigDto,
  string
>({
  formLayout: { labelCol: { span: 3 }, wrapperCol: { span: 20 } },
  rules: {
    name: [{ required: true, message: "请输入报表名称信息" }],
    code: [{ required: true, message: "请输入报表编码信息" }],
    categoryId: [{ required: true, message: "请选择报表分类" }],
  },
  model: {
    name: "",
    code: "",
    categoryId: "",
    dataSource: {
      apiConfigCode: "",
      remoteUrl: "",
      itemsField: "",
      summaryField: "",
      totalField: "",
      isPaged: false,
      hasSummary: false,
    },
    permissionName: "",
    requestOptions: [],
    reportColumns: [],
    summaryColumns: [],
    reportProps: {},
    status: true,
    sortIndex: 0,
    remarks: "",
  },
});
const itemsLibSource = ["declare const items:Array<Record<string,any>>;"].join(
  "\r\n"
);

const customCellLibSource = [
  "declare type ColumnConfigType={title:string;dataIndex:string;width?:number|string; align?:'left'|'center'|'right'; }",
  "declare const items:Array<Record<string,any>>;",
  "declare const index:number;",
  "declare const column:ColumnConfigType;",
].join("\r\n");
const formatterModel = ref<{ visible: boolean; config?: ReportColumnConfig }>({
  visible: false,
});

const componentModel = ref<{ visible: boolean; config?: ComponentOptions }>({
  visible: false,
});

const selectApiModel = ref<{ visible: boolean }>({ visible: false });

const isEdit = computed(() => {
  return props.action === "edit";
});

/**
 * 弹窗标题
 */
const title = computed(() => {
  return isEdit.value ? "修改查询报表信息" : "添加查询报表信息";
});

const showConfigComponent = (item: ReportRequestFieldItem) => {
  if (!item.componentOptions) {
    item.componentOptions = {
      name: "a-input",
      className: "",
      props: {},
      styles: {},
    };
  }
  componentModel.value = {
    visible: true,
    config: item.componentOptions,
  };
};
/**
 * 加载数据
 */
const loadData = () => {
  if (isEdit.value) {
    loading.value = true;
    api.get(props.id).then((res) => {
      if (!res.dataSource) {
        res.dataSource = {
          apiConfigCode: "",
          remoteUrl: "",
          itemsField: "",
          summaryField: "",
          totalField: "",
          isPaged: false,
          hasSummary: false,
        };
      } else {
        res.dataSource.apiConfigCode = res.dataSource.apiConfigCode || "";
        res.dataSource.isPaged = res.dataSource.isPaged || false;
        res.dataSource.hasSummary = res.dataSource.hasSummary || false;
      }
      Object.assign(model, res);

      loading.value = false;
    });
  }
};

/**
 * 提交
 */
const onSubmit = () => {
  emits("success");
  formRef.value.validate().then(() => {
    let request = isEdit.value
      ? api.update(props.id, model)
      : api.create(model);
    submitLoading.value = true;
    request
      .then((res) => {
        emits("success", res);
        emits("update:visible", false);
        emits("close");
      })
      .finally(() => {
        submitLoading.value = false;
      });
  });
};

/**
 * 取消
 */
const onCancel = () => {
  emits("update:visible", false);
  emits("close");
};

const showApiConfig = () => {
  selectApiModel.value = { visible: true };
};

watch(
  () => props.visible,
  (val: boolean) => {
    console.log("visible changed,val,", val);
    val && loadData();
  },
  { immediate: true }
);
</script>

<style lang="less" scoped>
.tabs {
  margin-top: -12px;

  .grid {
    border: 1px solid #ddd;
    min-height: 360px;
  }
  .row {
    border-bottom: 1px solid #ddd;
    display: flex;
    align-items: center;
    &-header {
      font-weight: bold;
      background: #eee;
    }
    .cell {
      padding: 5px;

      &-req-name {
        flex: 1.5;
      }
      &-req-desc {
        flex: 2;
      }
      &-req-value {
        flex: 1;
      }

      &-req-type {
        flex: 1;
      }
      &-req-input {
        flex: 1.5;
        overflow: hidden;
        text-overflow: ellipsis;
      }

      &-req-action {
        flex: 1;
      }

      &-name {
        flex: 1;
      }
      &-title {
        flex: 1.5;
      }
      &-width {
        flex: none;
        width: 90px;
      }
      &-align {
        flex: none;
        width: 110px;
      }
      &-format {
        flex: none;
        width: 100px;
        text-align: center;
      }

      &-action {
        flex: none;
        width: 100px;
      }
    }
  }

  .bar {
    padding: 10px 0;
  }
}
</style>
